// 
// File:   prism_driver.cc
// Author: cionescu
//
// Created on 8 January 2007, 15:07
//

#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <boost/spirit/core.hpp>
#include <boost/spirit/core/primitives/primitives.hpp>
#include <boost/spirit/tree/ast.hpp>
#include <boost/spirit/tree/common.hpp>
#include <boost/spirit/tree/parse_tree.hpp>
#include "ast_iterator.h"

#include <map>

#include "prism_driver.h"
//#include "prism_token.h"
#include "prism_parser.h"
#include "prism_scanner.h"
#include "prism_actions.h"
using namespace boost::spirit;
using namespace std;
namespace {
    
    
    char*
    load_file(const char* name) {
        int file_length;
        char *buffer;
        
        ifstream file_stream(name, ios::binary);
        
        // file length
        file_stream.seekg(0, ios::end);
        file_length = file_stream.tellg();
        
        // copy
        file_stream.seekg(0, ios::beg);
        buffer = new char[file_length];
        file_stream.read(buffer, file_length);
        
        file_stream.close();
        return buffer;
    }
    
    void
    print_tree() {
        
    }
    
    struct eval{    
        //parses the tree in a bottom-up manner
    template<typename node_t, typename context_t>
    long evaluate(node_t& container, context_t& context) {
        typedef typename node_t::iterator iterator;
        iterator begin = container.begin();
        iterator end = container.end();
        
        for (iterator it = begin; it!=end; it++) {
            evaluate(it->children, context); 
            handle(*it, context);
        }
        return 0;
    }
    
    template<typename value_t, typename context_t>
    long handle(value_t& value, context_t& context) {return 0;}
    };
}

/**
This is the main driver method.
*/
bool
prism_driver::generate_tree() {
    // read file
    char* buff;
    int file_length;
    
    m_file.seekg(0, ios::end);
    file_length = m_file.tellg();

    // copy
    m_file.seekg(0, ios::beg);
    buff = new char[file_length];
    m_file.read(buff, file_length);
    
    // feed characters to scanner and get vector of tokens + symbol table
    scanner_data sd;
    prism_scanner<scanner_data> scanner(sd);
    
    clog<<"scanner has started!"<<endl;
    parse_info<> scan_result = parse(buff, scanner); 
    clog<<"scanner has finished!"<<endl;
    
    // feed token vector to scanner and symbol table and get parse tree
    prism_parser<scanner_data> parser(sd);
    
    
    clog<<"parser has started! stream length:"<< sd.m_token_stream.size()<<endl;
    typedef vector<token*>::iterator iterator_t;
    tree_parse_info<iterator_t> tpi = 
    ast_parse(sd.m_token_stream.begin(), sd.m_token_stream.end(), parser); 
    clog<<"parser has finished! full:"<<tpi.full<<endl;
    
    /*typedef typeof tpi.trees container_t;
    typedef typeof tpi.trees.begin() tree_iterator_t;
    eval e;
    int i;
    long a = e.evaluate(tpi.trees, i); 
    /*for(tree_iterator_t it = tpi.trees.begin(); it!=tpi.trees.end(); it++) {
        container_t container = (*it).children;
        for (tree_iterator_t it1 = container.begin(); it1!=container.end(); it1++) {
            cout<<((*it1).value.id().to_long())<<endl;
        }
    }*/
    /*typedef tree_match<iterator_t>::container_t value_t;
    typedef parse_tree_iterator<tree_match<iterator_t>, value_t > parse_tree_iterator_t;
    //typedef parse_tree_iterator<tree_match<iterator_t> > parse_tree_iterator_t;
    
    parse_tree_iterator_t first(tpi.trees, tpi.trees.begin());
    parse_tree_iterator_t last;
    parse(first, last, nothing_p, nothing_p);*/
    
    return true;
}
